﻿#define _HAS_STD_BYTE 0

#include <iostream>
#include <ranges>
#include <vector>
#include <sstream>
#include <string>
#include <regex>
#include <iomanip>
#include <shared_mutex>
#include <mutex>
#include <memory>

#include <time.h>

using namespace std;


#include <atlbase.h>
#include <netcfgn.h>
#include <netcfgx.h>
#include <NetCon.h>
#include <Windows.h>

#ifndef __INetConnectionPropertyUi_INTERFACE_DEFINED__
#define __INetConnectionPropertyUi_INTERFACE_DEFINED__
EXTERN_C const IID IID_INetConnectionPropertyUi;
#if defined(__cplusplus) && !defined(CINTERFACE)
struct INetConnectionPropertyUi : public IUnknown {
public:
    virtual HRESULT WINAPI SetConnection(INetConnection* pCon) = 0;
    virtual HRESULT WINAPI AddPages(HWND hwndParent, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam) = 0;
};
#else
typedef struct INetConnectionPropertyUiVtbl {
    BEGIN_INTERFACE
        HRESULT(WINAPI* QueryInterface)(INetConnectionPropertyUi* This, REFIID riid, void** ppvObject);
    ULONG(WINAPI* AddRef)(INetConnectionPropertyUi* This);
    ULONG(WINAPI* Release)(INetConnectionPropertyUi* This);
    HRESULT(WINAPI* SetConnection)(INetConnectionPropertyUi* This, INetConnection* pCon);
    HRESULT(WINAPI* AddPages)(INetConnectionPropertyUi* This, HWND hwndParent, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
    END_INTERFACE
} INetConnectionPropertyUiVtbl;
struct INetConnectionPropertyUi {
    CONST_VTBL struct INetConnectionPropertyUiVtbl* lpVtbl;
};
#ifdef COBJMACROS
#define INetConnectionPropertyUi_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
#define INetConnectionPropertyUi_AddRef(This) (This)->lpVtbl->AddRef(This)
#define INetConnectionPropertyUi_Release(This) (This)->lpVtbl->Release(This)
#define INetConnectionPropertyUi_SetConnection(This,pCon) (This)->lpVtbl->SetConnection(This,pCon)
#define INetConnectionPropertyUi_AddPages(This,hwndParent,pfnAddPage,lParam) (This)->lpVtbl->AddPages(This,hwndParent,pfnAddPage,lParam)
#endif
#endif
HRESULT WINAPI INetConnectionPropertyUi_SetConnection_Proxy(INetConnectionPropertyUi* This, INetConnection* pCon);
void __RPC_STUB INetConnectionPropertyUi_SetConnection_Stub(IRpcStubBuffer* This, IRpcChannelBuffer* _pRpcChannelBuffer, PRPC_MESSAGE _pRpcMessage, DWORD* _pdwStubPhase);
HRESULT WINAPI INetConnectionPropertyUi_AddPages_Proxy(INetConnectionPropertyUi* This, HWND hwndParent, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
void __RPC_STUB INetConnectionPropertyUi_AddPages_Stub(IRpcStubBuffer* This, IRpcChannelBuffer* _pRpcChannelBuffer, PRPC_MESSAGE _pRpcMessage, DWORD* _pdwStubPhase);
#endif


HRESULT GetNetConnection(LPCWSTR name, INetConnection** ppConnection)
{
    INetConnectionManager* pConnectionManager;
    IEnumNetConnection* pEnumConnection;

    HRESULT hr = CoCreateInstance(CLSID_ConnectionManager, NULL, CLSCTX_ALL,
        IID_INetConnectionManager, (void**)&pConnectionManager);
    if (FAILED(hr))
    {
        return hr;
    }

    hr = pConnectionManager->EnumConnections(NCME_DEFAULT, &pEnumConnection);
    if (FAILED(hr))
    {
        return hr;
    }

    *ppConnection = 0;
    ULONG count;
    bool foundExpectedConnection = false;

    while (pEnumConnection->Next(1, ppConnection, &count) == S_OK)
    {
        NETCON_PROPERTIES* pProps = 0;
        hr = (*ppConnection)->GetProperties(&pProps);
        if (SUCCEEDED(hr))
        {
            if (wcscmp(pProps->pszwName, name) == 0)
            {
                foundExpectedConnection = true;
                break;
            }

            //NcFreeNetconProperties(pProps);
        }

        (*ppConnection)->Release();
    }

    pEnumConnection->Release();
    pConnectionManager->Release();

    return foundExpectedConnection ? S_OK : E_INVALIDARG;
}


HRESULT ShowIPv4PropertiesDialog(HWND hParentWnd, LPCWSTR networkName)
{
    HRESULT hr = S_OK;
    hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        return hr;
    }

    INetConnection* pConnection = 0;
    hr = GetNetConnection(networkName, &pConnection);
    if (FAILED(hr))
    {
        // Not found network
        return hr;
    }

    CComPtr<INetConnectionPropertyUi> pNetConnectionPropertyUi;
    CLSID uiClsid;

    if (SUCCEEDED(pConnection->GetUiObjectClassId(&uiClsid)))
    {
        CComPtr<IUnknown> pUnk;
        if (SUCCEEDED(pUnk.CoCreateInstance(uiClsid)))
        {
            hr = pUnk->QueryInterface(IID_INetConnectionPropertyUi, (void**)&pNetConnectionPropertyUi);
            if (FAILED(hr))
            {
                return hr;
            }

            hr = pNetConnectionPropertyUi->SetConnection(pConnection);
            if (FAILED(hr))
            {
                return hr;
            }
        }
    }

    CComPtr<INetCfg> pNetCfg;
    hr = pNetCfg.CoCreateInstance(CLSID_CNetCfg);
    if (SUCCEEDED(hr))
    {
        CComPtr<INetCfgLock> pNetCfgLock;
        hr = pNetCfg->QueryInterface(IID_INetCfgLock, (void**)&pNetCfgLock);
        if (SUCCEEDED(hr))
        {
            hr = pNetCfgLock->AcquireWriteLock(15000, TEXT("IPv4"), NULL);
            if (SUCCEEDED(hr))
            {
                hr = pNetCfg->Initialize(NULL);
                if (SUCCEEDED(hr))
                {
                    CComPtr<INetCfgComponent> pTcpIp;
                    if (SUCCEEDED(pNetCfg->FindComponent(NETCFG_TRANS_CID_MS_TCPIP, &pTcpIp)))
                    {
                        hr = pTcpIp->RaisePropertyUi(hParentWnd, NCRP_SHOW_PROPERTY_UI,
                            pNetConnectionPropertyUi);

                        if (SUCCEEDED(hr))
                        {
                            hr = pNetCfg->Apply();
                        }
                    }

                    pNetCfg->Uninitialize();
                }

                pNetCfgLock->ReleaseWriteLock();
            }
        }

        pNetCfg.Release();
    }

    pNetConnectionPropertyUi.Release();

    CoUninitialize();

    return hr;
}


int main()
{
    ShowIPv4PropertiesDialog(GetConsoleWindow(), L"WLAN 2");
    return 0;
}
